#include "string_test_base.h"

TEST(bp_u8string_test, null_input)
{
	EXPECT_EQ(nullptr, bp_u8string_get_cstr(nullptr));
	EXPECT_EQ(0, bp_u8string_length(nullptr));
	EXPECT_FALSE(bp_u8string_next_u8char(nullptr, nullptr));
}

#define _BYTES_SIZE(bytes) sizeof(bytes) / sizeof(*bytes)

TEST(bp_u8string_test, from_bytes)
{
	const bp_char32_t u8chars[] = {0xA0BDE4, 0xBDA5E5};

	const bp_byte_t u8[] = {0xe4, 0xbd, 0xa0, 0xe5, 0xa5, 0xbd};
	const bp_byte_t ansi[] = {0xc4, 0xe3, 0xba, 0xc3};
	const bp_byte_t u8bom[] = {0xef, 0xbb, 0xbf, 0xe4, 0xbd, 0xa0, 0xe5, 0xa5, 0xbd};
	const bp_byte_t u16le[] = {0x69, 0x4f, 0x7d, 0x59};
	const bp_byte_t u16lebom[] = {0xff, 0xfe, 0x69, 0x4f, 0x7d, 0x59};
	const bp_byte_t u16be[] = {0x4f, 0x69, 0x59, 0x7d};
	const bp_byte_t u16bebom[] = {0xfe, 0xff, 0x4f, 0x69, 0x59, 0x7d};

	vector<bytes_input> inputList;
	inputList.push_back(bytes_input(ansi, _BYTES_SIZE(ansi), bp_string_encode_ansi));
	inputList.push_back(bytes_input(u8, _BYTES_SIZE(u8), bp_string_encode_utf8));
	inputList.push_back(bytes_input(u8bom, _BYTES_SIZE(u8bom), bp_string_encode_utf8));
	inputList.push_back(bytes_input(u16le, _BYTES_SIZE(u16le), bp_string_encode_utf16le));
	//inputList.push_back(bytes_input(u16lebom, _BYTES_SIZE(u16le), bp_string_encode_utf16le));
	for (auto iter = inputList.begin(); iter != inputList.end(); ++iter)
	{
		bp_u8string_t string_from_bytes = bp_u8string_from_bytes(iter->getBytes(), iter->getSize(), iter->charset);
		EXPECT_EQ(_BYTES_SIZE(u8), bp_u8string_length(string_from_bytes));
		EXPECT_TRUE(memcmp(u8, bp_u8string_get_cstr(string_from_bytes), _BYTES_SIZE(u8)) == 0);

		bp_string_enumerate_state state;
		bp_string_enumerate_state_init(&state);
		//bp_char32_t u8result;
		EXPECT_TRUE(bp_u8string_next_u8char(string_from_bytes, &state));
		EXPECT_EQ(u8chars[0], state.charater);
		EXPECT_FALSE(state.end_of_string);

		EXPECT_TRUE(bp_u8string_next_u8char(string_from_bytes, &state));
		EXPECT_EQ(u8chars[1], state.charater);
		EXPECT_FALSE(state.end_of_string);

		EXPECT_TRUE(bp_u8string_next_u8char(string_from_bytes, &state));
		//EXPECT_EQ(0, state->charater);
		EXPECT_TRUE(state.end_of_string);
		bp_u8string_free(string_from_bytes);
	}
}

TEST(bp_u8string_test, enumarate_codepoint)
{
	auto tables = createTestUnicodeTable();
	size_t charscount = tables.size();
	string u8input;
	for (auto iter = tables.begin(); iter != tables.end(); ++iter)
	{
		u8input.append(iter->u8);
	}

	bp_u8string_t u8str = bp_u8string_from_bytes((const bp_byte_t *)u8input.data(), u8input.size(), bp_string_encode_utf8);
	EXPECT_EQ(u8input.size(), bp_u8string_length(u8str));

	//bp_char32_t u8char;
	bp_string_enumerate_state state;
	bp_string_enumerate_state_init(&state);
	for (size_t i = 0; i < charscount; ++i)
	{
		EXPECT_TRUE(bp_u8string_next_u8char(u8str, &state));
		EXPECT_EQ(tables[i].u8char, state.charater);
		EXPECT_FALSE(state.end_of_string);
	}

	EXPECT_TRUE(bp_u8string_next_u8char(u8str, &state));
	EXPECT_TRUE(state.end_of_string);
	//EXPECT_EQ(0, u8char);

	//bp_char32_t u32char;
	bp_string_enumerate_state_init(&state);
	for (size_t i = 0; i < charscount; ++i)
	{
		EXPECT_TRUE(bp_u8string_next_codepoint(u8str, &state));
		EXPECT_FALSE(state.end_of_string);
		EXPECT_EQ(tables[i].codepoint, state.charater);
	}

	EXPECT_TRUE(bp_u8string_next_codepoint(u8str, &state));
	EXPECT_TRUE(state.end_of_string);
	//EXPECT_EQ(0, u32char);

	bp_u8string_free(u8str);
}